package egg_drop;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;

import egg_drop.Framework.GameState;

public class Game {

    
    private ObBasket playerbasket;
    
    private ArrayList<ObPoo> poo;
    
    private ArrayList<AnimGoose> goose;
    
    private ArrayList<AnimHen> hen;
    
    private ArrayList<AnimDuck> duck;
    
    private ArrayList<ObEgg> eggs;
    
    private int score;
    
    private BufferedImage eggImg;
    
    private BufferedImage backgroundImg;
    
    private BufferedImage pooImg;
    
    private BufferedImage henImg;
    
    private BufferedImage duckImg;  
      
    private BufferedImage gooseImg;
    
    private int num;
    
    private int buffer;
    
    private int eggSpeed;
    
    private int missedEggs;
    
    private int pooCaught;
    
    private int eggX;
    
    private int eggY;
    
    private int difficulty;
    
    private static long lastAnimTime = 0;
    
    private static long timeBetweenAnim = Framework.secInNanosec * 3;

    public Game()
    {
        Framework.gameState = Framework.GameState.GAME_CONTENT_LOADING;
        
        Thread threadForInitGame = new Thread() {
            @Override
            public void run(){
                Initialize();
                LoadContent();
                RestartGame();
                
                Framework.gameState = Framework.GameState.PLAYING;
            }
        };
        threadForInitGame.start();
    }
    
         
    private void Initialize()
    {
        playerbasket = new ObBasket();
        eggs = new ArrayList<ObEgg>();
        poo = new ArrayList<ObPoo>();
        goose = new ArrayList<AnimGoose>();
        duck = new ArrayList<AnimDuck>();
        hen = new ArrayList<AnimHen>();
    }
    
    private void LoadContent()
    {
        try
        {
        	            
            URL eggUrl = this.getClass().getResource("/egg_drop/resources/egg.png");
            eggImg = ImageIO.read(eggUrl);
            
            URL pooUrl = this.getClass().getResource("/egg_drop/resources/shit.png");
            pooImg = ImageIO.read(pooUrl);
            
            backgroundImg = new BufferedImage(Framework.frameWidth, Framework.frameHeight, BufferedImage.TYPE_BYTE_BINARY);
            Graphics g = backgroundImg.createGraphics();
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, Framework.frameWidth, Framework.frameHeight);
            
            URL duckUrl = this.getClass().getResource("/egg_drop/resources/duck.png");
            duckImg = ImageIO.read(duckUrl);
            
            URL gooseUrl = this.getClass().getResource("/egg_drop/resources/goose.png");
            gooseImg = ImageIO.read(gooseUrl);
            
            URL henUrl = this.getClass().getResource("/egg_drop/resources/hen.png");
            henImg = ImageIO.read(henUrl);
            
        }
        catch (IOException ex) {
            Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
      
     
    public void RestartGame()
    {
    	eggs.clear();
        poo.clear();
        hen.clear();
        duck.clear();
        goose.clear();
    	playerbasket.ResetPlayer();
    	Random rand = new Random();
        num = rand.nextInt(Framework.frameWidth - 100);    	
        hen.add(new AnimHen(50 + num, 0, 2, henImg));
        num = rand.nextInt(Framework.frameWidth - 100);  
        duck.add(new AnimDuck(50 + num, 0, 2, duckImg));
        goose.add(new AnimGoose(Framework.frameWidth /2, 0, 2, gooseImg));
                
        ObEgg.lastEggTime = 0;
        lastAnimTime = 0;
        eggSpeed = 2;
        score = 0;
        missedEggs = 0;
        pooCaught = 0;
        difficulty = 1;

    }    
    
    public void UpdateGame(long gameTime, Point mousePosition)
    {
        
    	if(Canvas.keyboardKeyState(KeyEvent.VK_A) && (System.nanoTime() - lastAnimTime >= timeBetweenAnim))
        {
        	Random rand = new Random();
        	num = rand.nextInt(Framework.frameWidth - 100);    	
            hen.add(new AnimHen(50 + num, 0, 2, henImg));
            lastAnimTime = System.nanoTime();
        }
        if(Canvas.keyboardKeyState(KeyEvent.VK_S) && (System.nanoTime() - lastAnimTime >= timeBetweenAnim))
        {
        	Random rand = new Random();
        	num = rand.nextInt(Framework.frameWidth - 100);    	
            duck.add(new AnimDuck(50 + num, 0, 2, duckImg));
            lastAnimTime = System.nanoTime();
        }
        if(Canvas.keyboardKeyState(KeyEvent.VK_D) && (System.nanoTime() - lastAnimTime >= timeBetweenAnim))
        {
        	Random rand = new Random();
        	num = rand.nextInt(Framework.frameWidth - 100);    	
            goose.add(new AnimGoose(50 + num, 0, 2, gooseImg));
            lastAnimTime = System.nanoTime();
        }
    	
    	playerbasket.Update(mousePosition);
        
        for (int h = 0; h < hen.size(); h++)
        {
        	hen.get(h).Update();
        }
        
        for (int g = 0; g < goose.size(); g++)
        {
        	goose.get(g).Update();
        }
        
        for (int d = 0; d < duck.size(); d++)
        {
        	duck.get(d).Update();
        }

        gameTime += 1;
        
        Random rand = new Random();
        Random det = new Random();
        num = rand.nextInt(3);
        if (System.nanoTime() - ObEgg.lastEggTime >= ObEgg.timeBetweenEggs)
        {
        	if (num == 0)
        	{
        		buffer = det.nextInt(hen.size());
        		eggX = hen.get(buffer).x;
        		eggY = hen.get(buffer).y + 100;
        	}
        	if (num == 1)
        	{
        		buffer = det.nextInt(goose.size());
        		eggX = goose.get(buffer).x;
        		eggY = goose.get(buffer).y + 100;
        	}
        	if (num == 2)
        	{
        		buffer = det.nextInt(duck.size());
        		eggX = duck.get(buffer).x;
        		eggY = duck.get(buffer).y + 100;
        	}
        	
        	num = rand.nextInt(100);
        	if (num < 90)
        	{
        		eggs.add(new ObEgg(eggX, eggY, eggSpeed, eggImg));
        	}
        	else
        	{
        		poo.add(new ObPoo(eggX, eggY, eggSpeed, pooImg));
        	}
        	
        	ObEgg.lastEggTime = System.nanoTime();
        	
        }
        
        for(int i = 0; i < eggs.size(); i++)
        {
        	eggs.get(i).Update();
        	
        	if (Math.abs(eggs.get(i).x - playerbasket.x) <= 50 && Math.abs(eggs.get(i).y - playerbasket.y) <= 50)
        	{
        		eggs.remove(i);
        		score++;
        		if ((score % 20) == 0)
        		{
        			eggSpeed = (int) (eggSpeed * (difficulty * 1.5));
        			difficulty++;
        		}
        	} else if (eggs.get(i).y >= Framework.frameHeight - 70)
        	{
        		eggs.remove(i);
        		missedEggs++;
        		if (missedEggs >= 3)
        		{
        			Framework.gameState = Framework.GameState.GAMEOVER;
        		}
        	}
        	
        }
        
        for(int j = 0; j < poo.size(); j++)
        {
        	poo.get(j).Update();
        	
        	if (Math.abs(poo.get(j).x - playerbasket.x) <= 50 && Math.abs(poo.get(j).y - playerbasket.y) <= 50)
        	{
        		poo.remove(j);
        		pooCaught++;
        		if (pooCaught >= 3)
        		{
        			Framework.gameState = Framework.GameState.GAMEOVER;
        		}
        	} else if (poo.get(j).y >= Framework.frameHeight - 70)
        	{
        		poo.remove(j);        		
        	}
        }
    }
    
    public void Draw(Graphics2D g2d, Point mousePosition)
    {
        g2d.drawImage(backgroundImg, 0, 0, Framework.frameWidth, Framework.frameHeight, null);
                
        playerbasket.Draw(g2d);
        
        for (int h = 0; h < hen.size(); h++)
        {
        	hen.get(h).Draw(g2d);
        }
        for (int d = 0; d < duck.size(); d++)
        {
        	duck.get(d).Draw(g2d);
        }
        
        for (int g = 0; g < goose.size(); g++)
        {
        	goose.get(g).Draw(g2d);
        }
        
        for(int i = 0; i < eggs.size(); i++)
        {
        	eggs.get(i).Draw(g2d);
        	
        }
        for(int j =0; j < poo.size(); j++)
        {
        	poo.get(j).Draw(g2d);
        }
        
        g2d.drawString("Missed: " + missedEggs, Framework.frameWidth - 150, Framework.frameHeight - 30);
        g2d.drawString("Caught: " + score, Framework.frameWidth - 150, Framework.frameHeight - 10);
        g2d.drawString("Poo: " + pooCaught, Framework.frameWidth - 150, Framework.frameHeight - 50);
    }
    
    
    public void DrawGameOver(Graphics2D g2d, Point mousePosition)
    {
    	
    	g2d.drawImage(backgroundImg, 0, 0, Framework.frameWidth, Framework.frameHeight, null);
        
        g2d.drawString("Press space or enter to restart.", Framework.frameWidth / 2 - 150, Framework.frameHeight / 3 + 70);
        g2d.drawString("Game over", Framework.frameWidth / 2 - 150, Framework.frameHeight / 3);
        g2d.drawString("You have caught: " + score + " eggs.", Framework.frameWidth / 2 - 150, Framework.frameHeight / 3 + 20);       
        
    }
}
